#include <iostream>
#include <vector>
#include <functional>
#include <unistd.h>
#include <cstdlib>
#include <string>
#include "Thread.hpp"
#include "BlockQueue.hpp"
#include "Task.hpp"

// 命名空间
using namespace std;
using ThreadModule::Thread;
// 类型
using task_t = function<void()>;
// using BlockQueue_t = BlockQueue<int>;
using BlockQueue_t = BlockQueue<Task>; // 类作为任务
// using BlockQueue_t = BlockQueue<task_t>;//阻塞队列中的数据是函数对象
using fun_t = function<void(BlockQueue_t &, std::string)>;

pthread_mutex_t mutex_print = PTHREAD_MUTEX_INITIALIZER;
void PrintLog()
{
    cout << "PrintLog..." << endl;
}
void Productor(BlockQueue_t &bq, std::string name) // 生产者线程
{
    srand(time(nullptr));

    // sleep(3);
    while (true)
    {
        // 1.获取数据
        int a = rand() % 10;
        int b = rand() % 10;
        Task task(a, b);
        // 2.生产数据
        bq.push(task);
        pthread_mutex_lock(&mutex_print);
        std::cout << "productor[" << name << "] : "  << task.DebugToString() << std::endl;
        pthread_mutex_unlock(&mutex_print);
        sleep(1);
    }
}

void Consumer(BlockQueue_t &bq, std::string name) // 消费者线程
{
    // 消费者负责从阻塞队列中取出数据
    //  int n = -1;
    // Task task;
    Task task;
    sleep(5);
    while (true)
    {
        sleep(1);
        bq.pop(task);
        // 处理任务
        // task.Excute();
        task();
        pthread_mutex_lock(&mutex_print);
        std::cout << "consumer[" << name << "] : " << task.ResultToString() << std::endl;
        pthread_mutex_unlock(&mutex_print);
    }
}

void InitComm(vector<Thread<BlockQueue_t>> &t, int num, fun_t fun, BlockQueue_t &bq)
{
    // 创建n个线程
    for (int i = 0; i < num; i++)
    {
        string name = "thread-" + to_string(i + 1);
        t.emplace_back(fun, bq, name);
        // t.back().Start();    // vector库容时，调用析构函数，Thread对象中的string成员指向野指针，如果旧线程恰好执行到Excute，访问_name就会段错误。
    }
}
void InitConsumer(vector<Thread<BlockQueue_t>> &t, int num, BlockQueue_t &bq)
{
    InitComm(t, num, Consumer, bq);
}

void InitProductor(vector<Thread<BlockQueue_t>> &t, int num, BlockQueue_t &bq)
{
    InitComm(t, num, Productor, bq);
}

void WaitAllThread(vector<Thread<BlockQueue_t>> &t)
{
    for (auto &e : t)
    {
        e.Join();
    }
}

void StartAll(vector<Thread<BlockQueue_t>> &t)
{
    for (auto &thread : t)
    {
        thread.Start();
    }
}
int main()
{
    BlockQueue_t *bq = new BlockQueue_t(3); // 初始化阻塞队列的容量
    // vector<Thread<ThreadData>> thread_vec;
    vector<Thread<BlockQueue_t>> thread_vec;
    InitProductor(thread_vec, 3, *bq);
    InitConsumer(thread_vec, 1, *bq);
    StartAll(thread_vec);
    WaitAllThread(thread_vec); // 等待所有线程

    delete bq;
}